import logging
import os
import sys
import inspect
from typing import Optional
from datetime import datetime
import logging.handlers

# 尝试导入请求上下文模块
try:
    from app.core.request_context import get_request_id

    REQUEST_CONTEXT_AVAILABLE = True
    print("✅ 成功导入 request_context 模块")
except ImportError as e:
    print(f"⚠️ 无法导入 request_context: {e}")
    REQUEST_CONTEXT_AVAILABLE = False

# 设置日志级别
LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO')


def setup_logging():
    """设置日志系统 - 全局初始化函数"""
    # 创建日志目录
    log_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'logs')
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    # 设置默认日志文件路径
    log_file = os.path.join(log_dir, f'app_{datetime.now().strftime("%Y%m%d")}.log')

    print(f"📝 日志系统初始化完成 - 日志文件: {log_file}")
    return log_file


class AgentLogger:
    """统一的日志模块"""

    def __init__(self, name: str):
        self.logger = logging.getLogger(name)

        # 设置日志级别
        log_level = getattr(logging, LOG_LEVEL, logging.INFO)
        self.logger.setLevel(log_level)

        # 避免重复添加处理器
        if not self.logger.handlers:
            # 创建日志格式
            formatter = logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(location_info)s - [%(request_id)s] - %(message)s',
                datefmt='%Y-%m-%d %H:%M:%S'
            )

            # 控制台处理器
            console_handler = logging.StreamHandler(sys.stdout)
            console_handler.setFormatter(formatter)
            self.logger.addHandler(console_handler)

            # 文件处理器
            log_file = setup_logging()
            if log_file:
                file_handler = logging.handlers.RotatingFileHandler(
                    log_file,
                    maxBytes=10 * 1024 * 1024,
                    backupCount=20,
                    encoding='utf-8'
                )
                file_handler.setFormatter(formatter)
                self.logger.addHandler(file_handler)

        self.logger.propagate = False

    def _get_caller_info(self) -> tuple:
        """获取调用者信息"""
        try:
            stack = inspect.stack()
            for frame_info in stack[2:]:
                frame = frame_info.frame
                filename = os.path.basename(frame.f_code.co_filename)
                lineno = frame_info.lineno
                func_name = frame.f_code.co_name

                if 'logger' not in filename.lower():
                    return f"{filename}:{func_name}:{lineno}", filename, lineno, func_name
            return "unknown:unknown:0", "unknown", 0, "unknown"
        except Exception:
            return "unknown:unknown:0", "unknown", 0, "unknown"

    def _get_request_id(self) -> str:
        """获取请求ID"""
        try:
            if REQUEST_CONTEXT_AVAILABLE:
                request_id = get_request_id()
                if request_id is None:
                    return "no-request"
                return request_id
            return "no-context"
        except Exception as e:
            return f"error-{str(e)}"

    def _log_with_caller_info(self, level: int, message: str):
        """记录带有调用者信息的日志"""
        try:
            location_info, filename, lineno, func_name = self._get_caller_info()
            request_id = self._get_request_id()

            record = self.logger.makeRecord(
                name=self.logger.name,
                level=level,
                fn=filename,
                lno=lineno,
                msg=message,
                args=(),
                exc_info=None,
                func=func_name
            )

            record.location_info = location_info
            record.request_id = request_id

            self.logger.handle(record)
        except Exception as e:
            self.logger.log(level, f"日志记录错误: {e} - 原始消息: {message}")

    def debug(self, message: str):
        self._log_with_caller_info(logging.DEBUG, message)

    def info(self, message: str):
        self._log_with_caller_info(logging.INFO, message)

    def warning(self, message: str):
        self._log_with_caller_info(logging.WARNING, message)

    def error(self, message: str):
        self._log_with_caller_info(logging.ERROR, message)

    def critical(self, message: str):
        self._log_with_caller_info(logging.CRITICAL, message)


def get_logger(name: str) -> AgentLogger:
    return AgentLogger(name)